package cn.kivensoft.util;

import java.lang.ref.WeakReference;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.BiConsumer;

/** 弱键值的字典缓存，键和值都是弱引用, 支持线程安全与不安全两种模式
 * @author kiven
 * @version 1.0.0
 */
final public class WeakCache<K, V> implements Cache<K, V> {
	private final WeakHashMap<K, WeakReference<V>> map = new WeakHashMap<>();
	private final Lock lock;

	/** 构造函数, 缺省为线程不安全 */
	public WeakCache() {
		lock = null;
	}

	/** 构造函数, 可选择线程安全或不安全方式
	 * @param isSynchronized true表示支持线程安全, false表示线程不安全
	 */
	public WeakCache(boolean isSynchronized) {
		super();
		lock = isSynchronized ? new ReentrantLock() : null;
	}

	/** 测试是否包含指定的键
	 * @param key 指定的键
	 * @return true包含, false不包含
	 */
	@Override
	public boolean containsKey(K key) {
		if (lock == null)
			return map.containsKey(key);
		else {
			lock.lock();
			try {
				return map.containsKey(key);
			} finally {
				lock.unlock();
			}
		}
	}

	/** 测试缓存是否线程安全的 */
	@Override
	public boolean isSynchronized() {
		return lock != null;
	}

	/** 设置键值
	 * @param key 键
	 * @param value 值
	 */
	@Override
	public void put(K key, V value) {
		if (key == null || value == null) return;
		WeakReference<V> ref = new WeakReference<>(value);
		if (lock == null)
			map.put(key, ref);
		else {
			lock.lock();
			try {
				map.put(key, ref);
			} finally {
				lock.unlock();
			}
		}
	}

	/** 获取指定键的值
	 * @param key 键
	 * @return 值, 找不到返回null
	 */
	@Override
	public V get(K key) {
		WeakReference<V> ref;
		if (lock == null)
			ref = map.get(key);
		else {
			lock.lock();
			try {
				ref = map.get(key);
			} finally {
				lock.unlock();
			}
		}
		return ref == null ? null : ref.get();
	}

	/** 清除所有缓存 */
	@Override
	public void clear() {
		if (lock == null)
			map.clear();
		else {
			lock.lock();
			try {
				map.clear();
			} finally {
				lock.unlock();
			}
		}
	}

	/** 获取缓存大小 */
	@Override
	public int size() {
		if (lock == null)
			return map.size();
		else {
			lock.lock();
			try {
				return map.size();
			} finally {
				lock.unlock();
			}
		}
	}

	/** 判断缓存是否为空
	 * @return true表示缓存为空, false不为空
	 */
	@Override
	public boolean isEmpty() { return size() == 0; }

	/** 回收被gc掉的空间 */
	@Override
	public void cycle() { size(); }

	@Override
	public void remove(K key) {
		if (lock == null)
			map.remove(key);
		else {
			lock.lock();
			try {
				map.remove(key);
			} finally {
				lock.unlock();
			}
		}
	}

	@Override
	public int capacity() {
		return Integer.MAX_VALUE;
	}

	@Override
	public void forEach(BiConsumer<K, V> func) {
		if (lock == null)
			_forEach(func);
		else {
			lock.lock();
			try {
				_forEach(func);
			} finally {
				lock.unlock();
			}
		}
	}

	private void _forEach(BiConsumer<K, V> func) {
		for (Map.Entry<K, WeakReference<V>> entry : map.entrySet()) {
			WeakReference<V> v = entry.getValue();
			func.accept(entry.getKey(), v == null ? null : v.get());
		}
	}
}
